package cc.rengu.oltp.service.base;

import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.BinInfoMapper;
import cc.rengu.oltp.service.common.dao.SysParamMapper;
import cc.rengu.oltp.service.common.dao.TxnNumMapMapper;
import cc.rengu.oltp.service.common.dao.TxnSensitiveCfgMapper;
import cc.rengu.oltp.service.common.dao.impl.BinInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SysParamMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.TxnNumMapMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.TxnSensitiveCfgMapperImpl;
import cc.rengu.oltp.service.common.entity.BinInfo;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.entity.TxnNumMap;
import cc.rengu.oltp.service.common.entity.TxnSensitiveCfg;
import cc.rengu.oltp.utility.annotation.BIZ_PROCESS;
import cc.rengu.oltp.utility.util.RedisUtil;
import com.alibaba.fastjson.JSON;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 通用共享缓存服务
 * Created by 王成 on 2020/2/3.
 */
public class DefaultCacheService extends CacheBaseService {

    @Override
    protected boolean customShareCacheLoad() throws Exception {
        /* Step1：加载卡BIN配置信息 */
        List<BinInfo> binInfoList = new ArrayList<>();
        BinInfoMapper binInfoMapper = new BinInfoMapperImpl();
        binInfoMapper.loadAllCardBinInfo(dbPoolCashNode, binInfoList);
        if (!binInfoList.isEmpty()) {
            rglog.info("加载全部卡BIN数据条数:{}", binInfoList.size());
            /* Step1.1：先清空Redis中的卡BIN配置信息 */
            RedisUtil.onceDel(AppParamConstant.CARD_BIN_CACHE);
            /* Step1.2：按照卡BIN前6位进行分组 */
            Map<String, List<BinInfo>> binInfoMap = new HashMap<>();
            for (BinInfo binInfo : binInfoList) {
                String binInfoKey = AppParamConstant.BIN_CACHE_KEY;
                if (binInfo.getBinNo().length() >= 6) {
                    binInfoKey = AppParamConstant.BIN_CACHE_KEY + binInfo.getBinNo().substring(0, 6);
                }
                if (!binInfoMap.isEmpty() && null != binInfoMap.get(binInfoKey)) {
                    binInfoMap.get(binInfoKey).add(binInfo);
                } else {
                    List<BinInfo> binInfos = new ArrayList<>();
                    binInfos.add(binInfo);
                    binInfoMap.put(binInfoKey, binInfos);
                }
            }
            int groupSize = binInfoMap.size();
            rglog.info("分组后卡BIN数据条数:{}，其中卡BIN长度>=6的数据条数:{}, 卡BIN长度<6的数据条数", groupSize, groupSize - 1, 1);
            for (String binInfoKey : binInfoMap.keySet()) {
                List<BinInfo> binInfoList1 = binInfoMap.get(binInfoKey);
                /* Step1.3：去掉重复项 */
                List<BinInfo> binInfoList2 = binInfoList1.stream().distinct().collect(Collectors.toList());
                /* Step1.4：按照卡BIN长度降序排序 */
                List<BinInfo> binInfoList3 = binInfoList2.stream().sorted(Comparator.comparing(BinInfo::getBinLen)).collect(Collectors.toList());
                Collections.reverse(binInfoList3);
                /* Step1.5：将卡BIN信息加载到缓存 */
                RedisUtil.hashSet(AppParamConstant.CARD_BIN_CACHE, binInfoKey, JSON.toJSONString(binInfoList3));
            }
        } else {
            rglog.warn("未配置卡BIN数据请确认卡BIN数据是否必需！！！！！！！！！！！！！！！！！！！！！");
        }

        /* Step2：加载系统参数信息 */
        List<SysParam> sysParamList = new ArrayList<>();
        SysParamMapper sysParamMapper = new SysParamMapperImpl();
        sysParamMapper.loadSysParamInfo(dbPoolCashNode, sysParamList);
        if (!sysParamList.isEmpty()) {
            /* Step2.1：去掉重复项 */
            List<SysParam> sysParamLists = sysParamList.stream().distinct().collect(Collectors.toList());
            sysParamLists = sysParamLists.stream().filter(item -> item.getParamStatus().equals(AppParamConstant.YES)).collect(Collectors.toList());
            /* Step2.2：按照法人行及参数类型进行整合 */
            Map<String, List<SysParam>> sysParamMap = new HashMap<>();
            for (SysParam sysParam : sysParamLists) {
                String sysParamKey = sysParam.getInstId().trim() + sysParam.getParamType().trim();
                List<SysParam> mapKeyValue = sysParamMap.get(sysParamKey);
                if (null != mapKeyValue && !mapKeyValue.isEmpty()) {
                    mapKeyValue.add(sysParam);
                    sysParamMap.put(sysParamKey, mapKeyValue);
                } else {
                    List<SysParam> sysParams = new ArrayList<>();
                    sysParams.add(sysParam);
                    sysParamMap.put(sysParamKey, sysParams);
                }
            }
            /* Step2.3：先清空Redis中的系统参数配置信息 */
            RedisUtil.onceDel(AppParamConstant.SYS_PARAM_CACHE);
            /* Step2.4：将系统参数加载到缓存 */
            for (String key : sysParamMap.keySet()) {
                RedisUtil.hashSet(AppParamConstant.SYS_PARAM_CACHE, key, JSON.toJSONString(sysParamMap.get(key)));
            }
        }
        /* Step3：加开源系统与内部系统交易码映射关系 */
        TxnNumMapMapper txnNumMapMapper = new TxnNumMapMapperImpl();
        List<TxnNumMap> txnNumMapList = new ArrayList<>();
        for (String dbCaseNodeName : dbPoolCashNode) {
            List<TxnNumMap> txnNumMaps = txnNumMapMapper.loadTxnNumMapInfo(dbCaseNodeName);
            if (null != txnNumMaps && !txnNumMaps.isEmpty()) {
                txnNumMapList.addAll(txnNumMaps);
            }
        }
        if (!txnNumMapList.isEmpty()) {
            RedisUtil.onceDel(AppParamConstant.TXN_NUM_MAP_CACHE);
            for (TxnNumMap txnNumMap : txnNumMapList) {
                String txnNumMapKey = txnNumMap.getInstId().trim() + txnNumMap.getMsgSrcId().trim() + txnNumMap.getTransChannelId().trim() + txnNumMap.getSrcTxnNum().trim();
                RedisUtil.hashSet(AppParamConstant.TXN_NUM_MAP_CACHE, txnNumMapKey, JSON.toJSONString(txnNumMap));
            }
        }
        /* Step4：加载交易敏感配置信息 */
        TxnSensitiveCfgMapper txnSensitiveCfgMapper = new TxnSensitiveCfgMapperImpl();
        List<TxnSensitiveCfg> txnSensitiveCfgList = new ArrayList<>();
        for (String dbCaseNodeName : dbPoolCashNode) {
            List<TxnSensitiveCfg> txnSensitiveCfgs = txnSensitiveCfgMapper.loadTxnSensitiveCfg(dbCaseNodeName);
            if (null != txnSensitiveCfgs && !txnSensitiveCfgs.isEmpty()) {
                txnSensitiveCfgList.addAll(txnSensitiveCfgs);
            }
        }
        if (!txnSensitiveCfgList.isEmpty()) {
            /* Step4.1：按照交易请求或者应答进行分类整合 */
            Map<String, List<TxnSensitiveCfg>> txnSensitiveMap = new HashMap<>();
            for (TxnSensitiveCfg txnSensitiveCfg : txnSensitiveCfgList) {
                String txnSensitiveKey = txnSensitiveCfg.getInstId().trim() + txnSensitiveCfg.getMsgSrcId().trim() + txnSensitiveCfg.getTxnNum().trim() + txnSensitiveCfg.getBizType().trim() + txnSensitiveCfg.getOprType().trim();
                List<TxnSensitiveCfg> sensitiveCfgs = txnSensitiveMap.get(txnSensitiveKey);
                if (null != sensitiveCfgs && !sensitiveCfgs.isEmpty()) {
                    sensitiveCfgs.add(txnSensitiveCfg);
                    txnSensitiveMap.put(txnSensitiveKey, sensitiveCfgs);
                } else {
                    List<TxnSensitiveCfg> txnSensitiveCfgs = new ArrayList<>();
                    txnSensitiveCfgs.add(txnSensitiveCfg);
                    txnSensitiveMap.put(txnSensitiveKey, txnSensitiveCfgs);
                }
            }
            /* Step4.2：先清空Redis中的交易敏感信息配置 */
            RedisUtil.onceDel(AppParamConstant.TXN_SENSITIVE_CFG_CACHE);
            /* Step4.3：将交易敏感信息配置加载到缓存 */
            for (String key : txnSensitiveMap.keySet()) {
                RedisUtil.hashSet(AppParamConstant.TXN_SENSITIVE_CFG_CACHE, key, JSON.toJSONString(txnSensitiveMap.get(key)));
            }
        }
        /* Step5：加载用户自定义的其它缓存信息 */
        invokeBizAnnoMethod(BIZ_PROCESS.class);
        return true;
    }
}
